module cpu_top(
    input wire clk,
    input wire resetn,

    //inst
    output wire         inst_rd_req,
    output wire[2 :0]   inst_rd_type,
    output wire[31:0]   inst_rd_addr,
    input  wire         inst_rd_rdy,
    input  wire         inst_ret_valid,
    input  wire         inst_ret_last,
    input  wire[31:0]   inst_ret_data,

    output  wire        inst_wr_req,
    output  wire[2 :0]  inst_wr_type,
    output  wire[31:0]  inst_wr_addr,//写首地址
    output  wire[3 :0]  inst_wr_wstrb,
    output  wire[127:0] inst_wr_data,
    input   wire        inst_wr_rdy,
    // //cpu data sram
    // output wire        data_sram_req,
    // output wire        data_sram_wr,
    // output wire [1 :0] data_sram_size,
    // output wire [3 :0] data_sram_wstrb,
    // output wire [31:0] data_sram_addr,
    // output wire [31:0] data_sram_wdata,
    // input wire        data_sram_addr_ok,
    // input wire        data_sram_data_ok,
    // input wire [31:0] data_sram_rdata,

    //data
    output wire         data_rd_req,
    output wire[2 :0]   data_rd_type,
    output wire[31:0]   data_rd_addr,
    input  wire         data_rd_rdy,
    input  wire         data_ret_valid,
    input  wire         data_ret_last,
    input  wire[31:0]   data_ret_data,

    output  wire        data_wr_req,
    output  wire[2 :0]  data_wr_type,
    output  wire[31:0]  data_wr_addr,//写首地址
    output  wire[3 :0]  data_wr_wstrb,
    output  wire[127:0] data_wr_data,
    input   wire        data_wr_rdy,





    // trace debug interface
    output wire [31:0] debug_wb_pc,
    output wire [ 3:0] debug_wb_rf_we,
    output wire [ 4:0] debug_wb_rf_wnum,
    output wire [31:0] debug_wb_rf_wdata
);
wire reset;
assign reset=~resetn;
wire[31:0] inst_IF_o;
wire[31:0] pc_IF_o;
wire IFU_ready_IF_o;
wire br_taken_ID_o;
wire[31:0] br_target_ID_o;
wire exc_IF_o;
wire[ 5:0] ecode_IF_o;
wire esubcode_IF_o;
wire[31:0] badv_IF_o;
//
wire[31:0] inst_IF_ID_o;
wire[31:0] cur_pc_IF_ID_o;
wire IF_ready_IF_ID_o;
wire exc_IF_ID_o;
wire[ 5:0] ecode_IF_ID_o;
wire esubcode_IF_ID_o;
wire[31:0] badv_IF_ID_o;

wire is_write_reg_ID_o;
wire is_read_mem_ID_o;
wire is_write_mem_ID_o;
wire res_from_mem_ID_o;
wire[3:0] mem_op_ID_o;
wire[18:0] alu_op_ID_o;
wire[4:0] dest_ID_o;
wire[31:0] rf_rdata1_ID_o;
wire[31:0] rf_rdata2_ID_o;
wire[4:0] rf_raddr1_ID_o;
wire[4:0] rf_raddr2_ID_o;
wire[31:0] imm_ID_o;
wire src2_is_imm_ID_o;
wire src1_is_pc_ID_o;
wire[31:0] pc_ID_o;
wire is_write_csr_ID_o;
wire[13:0] csr_dest_ID_o;
wire[13:0] csr_rdest_ID_o;
wire[31:0] csr_wdata_ID_o;
wire[31:0] csr_rdata_ID_o;
wire res_from_csr_ID_o; 
wire exc_ID_o;
wire[5:0] ecode_ID_o;
wire esubcode_ID_o;
wire exc_oc_ID_o;
//
wire is_write_reg_ID_EX_o;
wire is_write_mem_ID_EX_o;
wire res_from_mem_ID_EX_o;
wire[3:0] mem_op_ID_EX_o;
wire[4:0] dest_ID_EX_o;
wire[18:0] alu_op_ID_EX_o;
wire[31:0] alu_src1_ID_EX_o;
wire[31:0] alu_src2_ID_EX_o;
wire[31:0] rf_rdata2_ID_EX_o;
wire[4:0] rf_raddr1_ID_EX_o;
wire[4:0] rf_raddr2_ID_EX_o;
wire is_write_csr_ID_EX_o;
wire[31:0] pc_ID_EX_o;
wire[13:0] csr_dest_ID_EX_o;
wire[31:0] csr_wdata_ID_EX_o;
wire[31:0] csr_rdata_ID_EX_o;
wire res_from_csr_ID_EX_o;
wire exc_ID_EX_o;
wire [5:0] ecode_ID_EX_o;
wire esubcode_ID_EX_o;
wire [31:0] badv_ID_EX_o;
//
wire[31:0] alu_res_EX_o;
wire mulcal_EX_o;
//
wire is_write_reg_EX_MEM_o;
wire is_write_mem_EX_MEM_o;
wire res_from_mem_EX_MEM_o;
wire[3:0] mem_op_EX_MEM_o;
wire[4:0] dest_EX_MEM_o;
wire[31:0] pc_EX_MEM_o;
wire[31:0] alu_result_EX_MEM_o;
wire[31:0] fdata_EX_MEM_o;
wire[31:0] rf_rdata2_after_forward_EX_MEM_o;

wire is_write_csr_EX_MEM_o;
wire [13:0]csr_dest_EX_MEM_o;
wire [31:0]csr_wdata_EX_MEM_o;
wire [31:0]csr_rdata_EX_MEM_o;
wire res_from_csr_EX_MEM_o;
wire exc_EX_MEM_o;
wire [5:0] ecode_EX_MEM_o;
wire esubcode_EX_MEM_o;
wire [31:0] badv_EX_MEM_o;
//
wire busy_MEMU_o;
wire[31:0] res_data_MEM_o;
wire exc_MEM_o;
wire[5:0] ecode_MEM_o;
wire esubcode_MEM_o;
wire[31:0] badv_MEM_o;
//
wire[4:0] dest_MEM_WB_o;
wire is_write_reg_MEM_WB_o;
wire[31:0] wb_data_MEM_WB_o;
wire[31:0] pc_MEM_WB_o;
wire[31:0] csr_rf_waddr_MEM_WB_o;
wire[31:0] csr_rf_wdata_MEM_WB_o;
wire[31:0] csr_rf_we_MEM_WB_o;

wire exc_MEM_WB_o;
wire[6:0] exc_entry_MEM_WB_o;
wire[31:0] badv_MEM_WB_o;
//
wire[1:0] rf_raddr1_src_op_IF_ID_FORWARDU_o;
wire[1:0] rf_raddr2_src_op_IF_ID_FORWARDU_o;
wire block_flush_ID_FORWARDU_o;
wire br_taken;
wire block_before_MEM;
wire block_before_EX;
wire block_before_ID;
wire block_before_IF;
wire[1:0] csr_src_op_IF_ID_FORWARDU_o;
//阻塞条件
assign block_before_IF = ~exc_IF_o & ~IFU_ready_IF_o & (~block_before_ID & ~block_before_EX & ~block_before_MEM);
assign block_before_ID = ~exc_IF_o & (block_flush_ID_FORWARDU_o | br_taken_ID_o & ~IFU_ready_IF_o) & ( ~block_before_EX & ~block_before_MEM);
assign block_before_EX = (mulcal_EX_o | (is_write_mem_EX_MEM_o & res_from_mem_ID_EX_o)) & (~block_before_MEM);
assign br_taken = br_taken_ID_o & (~block_before_IF & ~block_before_ID& ~block_before_EX & ~block_before_MEM);
assign block_before_MEM = ~exc_MEM_o & busy_MEMU_o;
IFU IFU0(
    .clk(clk),
    .reset(reset | exc_oc_ID_o | exc_ID_o | exc_ID_EX_o | exc_EX_MEM_o | exc_MEM_WB_o),
    .br_taken(br_taken),
    .br_target(br_target_ID_o),
    .block(block_before_ID | block_before_EX | block_before_IF | block_before_MEM),
    //输出
    .inst(inst_IF_o),
    .pc_o(pc_IF_o),
    .exc(exc_IF_o),
    .ecode(ecode_IF_o),
    .esubcode(esubcode_IF_o),
    .badv(badv_IF_o),
    //
    .rd_req(inst_rd_req),
    .rd_type(inst_rd_type),
    .rd_addr(inst_rd_addr),
    .rd_rdy(inst_rd_rdy),
    .ret_valid(inst_ret_valid),
    .ret_last(inst_ret_last),
    .ret_data(inst_ret_data),

    .wr_req(inst_wr_req),//写请�?
    .wr_type(inst_wr_type),
    .wr_addr(inst_wr_addr),//写首地址
    .wr_wstrb(inst_wr_wstrb),
    .wr_data(inst_wr_data),
    .wr_rdy(inst_wr_rdy),

    .IFU_ready(IFU_ready_IF_o)
);

IF_ID IF_ID0(
    .clk(clk),
    .we(!(block_before_ID|block_before_EX|block_before_MEM)),
    .reset(reset | br_taken | block_before_IF | exc_oc_ID_o | exc_ID_o | exc_ID_EX_o | exc_EX_MEM_o | exc_MEM_WB_o),
    .inst(inst_IF_o),
    .cur_pc(pc_IF_o),
    .IF_ready(IFU_ready_IF_o),
    .exc(exc_IF_o),
    .ecode(ecode_IF_o),
    .esubcode(esubcode_IF_o),
    .badv(badv_IF_o),
    //输出
    .inst_o(inst_IF_ID_o),
    .cur_pc_o(cur_pc_IF_ID_o),
    .IF_ready_o(IF_ready_IF_ID_o),
    .exc_o(exc_IF_ID_o),
    .ecode_o(ecode_IF_ID_o),
    .esubcode_o(esubcode_IF_ID_o),
    .badv_o(badv_IF_ID_o)
);
IDU IDU0(
    .clk(clk),
    .inst(inst_IF_ID_o),
    .rst(reset),
    .rf_waddr(dest_MEM_WB_o),
    .rf_wdata(wb_data_MEM_WB_o),
    .rf_we(is_write_reg_MEM_WB_o),
    .pc_current(cur_pc_IF_ID_o),
    .ID_block(block_before_ID | block_before_EX | block_before_MEM),
    .IF_ready(IFU_ready_IF_o),
    //id级转发控�?
    .src1_op(rf_raddr1_src_op_IF_ID_FORWARDU_o),
    .src2_op(rf_raddr2_src_op_IF_ID_FORWARDU_o),
    .csr_op(csr_src_op_IF_ID_FORWARDU_o),
    //转发源输�?
    .dest_value_from_EX_MEM(fdata_EX_MEM_o),
    .dest_value_from_MEM_WB(wb_data_MEM_WB_o),
    .dest_value_from_ID_EX(csr_rdata_ID_EX_o),
    .csr_value_from_ID_EX(csr_wdata_ID_EX_o),
    .csr_value_from_EX_MEM(csr_wdata_EX_MEM_o),

    //输出
    .need_ID_forward1(),
    .need_ID_forward2(),
    .br_target(br_target_ID_o),
    .br_taken(br_taken_ID_o),
    .is_write_reg(is_write_reg_ID_o),
    .is_read_mem(is_read_mem_ID_o),
    .is_write_mem(is_write_mem_ID_o),
    .res_from_mem(res_from_mem_ID_o),
    .mem_op(mem_op_ID_o),
    .alu_op(alu_op_ID_o),
    .rf_rdata1(rf_rdata1_ID_o),
    .rf_rdata2(rf_rdata2_ID_o),
    .rf_raddr1(rf_raddr1_ID_o),
    .rf_raddr2(rf_raddr2_ID_o),
    .dest(dest_ID_o),
    .imm(imm_ID_o),
    .src2_is_imm(src2_is_imm_ID_o),
    .src1_is_pc(src1_is_pc_ID_o),
    .pc(pc_ID_o),

    ///exc
    .exc_in(exc_MEM_WB_o),
    .exc_pc(pc_MEM_WB_o),
    .exc_entry(exc_entry_MEM_WB_o),
    .badv(badv_MEM_WB_o),
    .csr_rf_waddr(csr_rf_waddr_MEM_WB_o),
    .csr_rf_wdata(csr_rf_wdata_MEM_WB_o),
    .csr_rf_we(csr_rf_we_MEM_WB_o),

    .is_write_csr(is_write_csr_ID_o),
    .csr_dest(csr_dest_ID_o),
    .csr_rdest(csr_rdest_ID_o),
    .csr_wdata(csr_wdata_ID_o),
    .csr_rdata(csr_rdata_ID_o),
    .res_from_csr(res_from_csr_ID_o),

    .exc(exc_ID_o),
    .ecode(ecode_ID_o),
    .esubcode(esubcode_ID_o),
    .exc_oc(exc_oc_ID_o)

    //inst_Ram
);

ID_EX ID_EX0(
    .we(!(block_before_EX | block_before_MEM)),
    .clk(clk),
    .reset(reset | block_before_ID | exc_EX_MEM_o | exc_MEM_o | exc_MEM_WB_o | exc_oc_ID_o),
    .is_write_reg_in(is_write_reg_ID_o),//if the instrcution write the register
    .is_write_mem_in(is_write_mem_ID_o),//if the instrcution write the memory
    .res_from_mem_in(res_from_mem_ID_o),//result source
    .mem_op_in(mem_op_ID_o),
    .dest_in(dest_ID_o),

    .alu_op_in(alu_op_ID_o),//alu opeation code
    .rf_rdata1_in(rf_rdata1_ID_o),
    .rf_rdata2_in(rf_rdata2_ID_o),
    .rf_raddr1_in(rf_raddr1_ID_o),// being used to transform,the register number of alu souce 1
    .rf_raddr2_in(rf_raddr2_ID_o),
    .imm_in(imm_ID_o),
    .src1_is_pc_in(src1_is_pc_ID_o),
    .src2_is_imm_in(src2_is_imm_ID_o),
    .pc_in(cur_pc_IF_ID_o),
//csr
    .is_write_csr_in(is_write_csr_ID_o),
    .csr_dest_in(csr_dest_ID_o),
    .csr_wdata_in(csr_wdata_ID_o),
    .csr_rdata_in(csr_rdata_ID_o),
    .res_from_csr_in(res_from_csr_ID_o),

    .is_write_reg(is_write_reg_ID_EX_o),//if the instrcution write the register
    .is_write_mem(is_write_mem_ID_EX_o),//if the instrcution write the memory
    .res_from_mem(res_from_mem_ID_EX_o),//result source
    .mem_op(mem_op_ID_EX_o),
    .dest(dest_ID_EX_o),

    .alu_op(alu_op_ID_EX_o),//alu opeation code
    .alu_src1(alu_src1_ID_EX_o),
    .alu_src2(alu_src2_ID_EX_o),
    .rf_rdata2(rf_rdata2_ID_EX_o),
    .rf_raddr1(rf_raddr1_ID_EX_o),// being used to transform,the register number of alu souce 1
    .rf_raddr2(rf_raddr2_ID_EX_o),
    .pc(pc_ID_EX_o),
//exc
    .is_write_csr(is_write_csr_ID_EX_o),
    .csr_dest(csr_dest_ID_EX_o),
    .csr_wdata(csr_wdata_ID_EX_o),
    .csr_rdata(csr_rdata_ID_EX_o),
    .res_from_csr(res_from_csr_ID_EX_o),

    .exc_in(exc_ID_o | exc_IF_ID_o),
    .ecode_in(exc_ID_o ? ecode_ID_o : ecode_IF_ID_o),
    .esubcode_in(exc_ID_o ? esubcode_ID_o : esubcode_IF_ID_o),
    .badv_in(badv_IF_ID_o),
    .exc(exc_ID_EX_o),
    .ecode(ecode_ID_EX_o),
    .esubcode(esubcode_ID_EX_o),
    .badv(badv_ID_EX_o)
);

EXU EXU0(
    //上一级段寄存器输�?
    .clk(clk),
    .reset(reset),
    .mulcal(mulcal_EX_o),
    .alu_op(alu_op_ID_EX_o),
    .alu_src1(alu_src1_ID_EX_o),
    .alu_src2(alu_src2_ID_EX_o),
    //输出
    .alu_res(alu_res_EX_o)
);
EX_MEM EX_MEM0(
    .we(~(block_before_MEM)),
    .clk(clk),
    .reset(reset | block_before_EX | exc_MEM_o | exc_MEM_WB_o),
    .is_write_reg_in(is_write_reg_ID_EX_o),//if the instrcution write the register
    .is_write_mem_in(is_write_mem_ID_EX_o),//if the instrcution write the memory
    .res_from_mem_in(res_from_mem_ID_EX_o),//result source
    .mem_op_in(mem_op_ID_EX_o),
    .dest_in(dest_ID_EX_o),
    .pc_in(pc_ID_EX_o),
    .alu_result_in(alu_res_EX_o),
    .rf_rdata2_after_forward_in(rf_rdata2_ID_EX_o),
//csr
    .is_write_csr_in(is_write_csr_ID_EX_o),
    .csr_dest_in(csr_dest_ID_EX_o),
    .csr_wdata_in(csr_wdata_ID_EX_o),
    .csr_rdata_in(csr_rdata_ID_EX_o),
    .res_from_csr_in(res_from_csr_ID_EX_o),


    .is_write_reg(is_write_reg_EX_MEM_o),//if the instrcution write the register
    .is_write_mem(is_write_mem_EX_MEM_o),//if the instrcution write the memory
    .res_from_mem(res_from_mem_EX_MEM_o),//result source
    .mem_op(mem_op_EX_MEM_o),
    .dest(dest_EX_MEM_o),
    .pc(pc_EX_MEM_o),
    .alu_result(alu_result_EX_MEM_o),
    .fdata(fdata_EX_MEM_o),
    .rf_rdata2_after_forward(rf_rdata2_after_forward_EX_MEM_o),
//csr
    .is_write_csr(is_write_csr_EX_MEM_o),
    .csr_dest(csr_dest_EX_MEM_o),
    .csr_wdata(csr_wdata_EX_MEM_o),
    .csr_rdata(csr_rdata_EX_MEM_o),
    .res_from_csr(res_from_csr_EX_MEM_o),

//exc
    .exc_in(exc_ID_EX_o),
    .ecode_in(ecode_ID_EX_o),
    .esubcode_in(esubcode_ID_EX_o),
    .badv_in(badv_ID_EX_o),

    .exc(exc_EX_MEM_o),
    .ecode(ecode_EX_MEM_o),
    .esubcode(esubcode_EX_MEM_o),
    .badv(badv_EX_MEM_o)
);
MEMU MEMU0(
    .clk(clk),
    .resetn(resetn),
    .mem_we(is_write_mem_EX_MEM_o),
    .mem_addr_alu(alu_res_EX_o),
    .mem_addr(alu_result_EX_MEM_o),//即alu_res
    .mem_w_data(rf_rdata2_after_forward_EX_MEM_o),
    .mem_op(mem_op_EX_MEM_o),//0为字//1为半�?//2为字�?
    .res_from_mem(res_from_mem_EX_MEM_o),
    .res_data(res_data_MEM_o),
    //exc
    .exc(exc_MEM_o),
    .ecode(ecode_MEM_o),
    .esubcode(esubcode_MEM_o),
    .badv(badv_MEM_o),


    //data_Ram
    .busy(busy_MEMU_o),

    //data
    .data_rd_req(data_rd_req),
    .data_rd_type(data_rd_type),
    .data_rd_addr(data_rd_addr),
    .data_rd_rdy(data_rd_rdy),
    .data_ret_valid(data_ret_valid),
    .data_ret_last(data_ret_last),
    .data_ret_data(data_ret_data),

    .data_wr_req(data_wr_req),
    .data_wr_type(data_wr_type),
    .data_wr_addr(data_wr_addr),//写首地址
    .data_wr_wstrb(data_wr_wstrb),
    .data_wr_data(data_wr_data),
    .data_wr_rdy(data_wr_rdy)
);

MEM_WB MEM_WB0(
    .we(1),
    .clk(clk),
    .reset(reset | block_before_MEM),
    .is_write_reg_in(is_write_reg_EX_MEM_o),//if the instrcution write the register
    .res_from_mem_in(res_from_mem_EX_MEM_o),//result source
    .dest_in(dest_EX_MEM_o),
    .pc_in(pc_EX_MEM_o),
    .alu_result_in(alu_result_EX_MEM_o),
    .mem_result_in(res_data_MEM_o),
//csr
    .is_write_csr_in(is_write_csr_EX_MEM_o),
    .csr_dest_in(csr_dest_EX_MEM_o),
    .csr_wdata_in(csr_wdata_EX_MEM_o),
    .csr_rdata_in(csr_rdata_EX_MEM_o),
    .res_from_csr_in(res_from_csr_EX_MEM_o),
//输出
    .is_write_reg(is_write_reg_MEM_WB_o),//if the instrcution write the register
    .dest(dest_MEM_WB_o),
    .pc(pc_MEM_WB_o),
    .wb_data(wb_data_MEM_WB_o),
//csr
    .is_write_csr(csr_rf_we_MEM_WB_o),
    .csr_dest(csr_rf_waddr_MEM_WB_o),
    .csr_wdata(csr_rf_wdata_MEM_WB_o),
//exc
    .exc_in(exc_MEM_o | exc_EX_MEM_o),
    .ecode_in(exc_MEM_o ? ecode_MEM_o : ecode_EX_MEM_o),
    .esubcode_in(exc_MEM_o ? esubcode_MEM_o : esubcode_EX_MEM_o),
    .badv_in(exc_MEM_o ? badv_MEM_o : badv_EX_MEM_o),

    .exc(exc_MEM_WB_o),
    .exc_entry(exc_entry_MEM_WB_o),
    .badv(badv_MEM_WB_o)
);
assign debug_wb_pc={8'h1c,pc_MEM_WB_o[23:0]};
assign debug_wb_rf_we={4{is_write_reg_MEM_WB_o}};
assign debug_wb_rf_wnum=dest_MEM_WB_o;
assign debug_wb_rf_wdata=wb_data_MEM_WB_o;

FORWARDU FORWARDU0(
    .is_read_memory_ID_EX(res_from_mem_ID_EX_o),
    .is_read_memory_EX_MEM(res_from_mem_EX_MEM_o),
    .is_write_reg_ID_EX(is_write_reg_ID_EX_o),
    .is_write_reg_EX_MEM(is_write_reg_EX_MEM_o),
    .is_write_reg_MEM_WB(is_write_reg_MEM_WB_o),
    .res_from_csr_ID_EX(res_from_csr_ID_EX_o),
    .dest_ID_EX(dest_ID_EX_o),
    .dest_EX_MEM(dest_EX_MEM_o),
    .dest_MEM_WB(dest_MEM_WB_o),

    .rf_raddr1_ID_EX(rf_raddr1_ID_EX_o),// the register number of alu souce 1
    .rf_raddr2_ID_EX(rf_raddr2_ID_EX_o),
    .Need_ID_forward1(),
    .Need_ID_forward2(),
    .rf_raddr1_IF_ID(rf_raddr1_ID_o),
    .rf_raddr2_IF_ID(rf_raddr2_ID_o),


    .csr_addr_ID(csr_rdest_ID_o),
    .csr_dest_ID_EX(csr_dest_ID_EX_o),
    .csr_dest_EX_MEM(csr_dest_EX_MEM_o),
    .is_write_csr_ID_EX(is_write_csr_ID_EX_o),
    .is_write_csr_EX_MEM(is_write_csr_EX_MEM_o),

    .csr_src_op(csr_src_op_IF_ID_FORWARDU_o),
    
//id控制
    .rf_raddr1_src_op_IF_ID(rf_raddr1_src_op_IF_ID_FORWARDU_o),
    .rf_raddr2_src_op_IF_ID(rf_raddr2_src_op_IF_ID_FORWARDU_o),
//阻塞id之前
    .block_flush_ID(block_flush_ID_FORWARDU_o)
);
endmodule
